using System.Runtime.InteropServices;
using System.Text;
using Microsoft.Extensions.Logging;

namespace KeyAuthService.Services
{
    /// <summary>
    /// KeyAuthCore DLL 封装类
    /// </summary>
    public class KeyAuthCore
    {
        private readonly ILogger<KeyAuthCore> _logger;

        // 错误码
        public const int SUCCESS = 0;
        public const int ERROR_GENERAL = 1;
        
        // 算法类型
        public const string ALGO_SM2 = "SM2";
        public const string ALGO_ECDSA_P256 = "ECDSA_P256";
        
        //--------------------------------------------------------------------
        // 密钥基础操作
        //--------------------------------------------------------------------
        [DllImport("keyauthcore.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern int KeyAuthGenerateKeyPair(
            [MarshalAs(UnmanagedType.LPStr)] string algo,
            out IntPtr pubKey,
            out IntPtr priKey);
        
        //--------------------------------------------------------------------
        // 请求数据操作
        //--------------------------------------------------------------------
        [DllImport("keyauthcore.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern int KeyAuthSignData(
            [MarshalAs(UnmanagedType.LPStr)] string priKey,
            [MarshalAs(UnmanagedType.LPStr)] string headerJson,
            [MarshalAs(UnmanagedType.LPStr)] string payloadJson,
            out IntPtr signature,
            out int signatureLen);
        
        [DllImport("keyauthcore.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern int KeyAuthVerifyData(
            [MarshalAs(UnmanagedType.LPStr)] string pubKey,
            [MarshalAs(UnmanagedType.LPStr)] string headerJson,
            [MarshalAs(UnmanagedType.LPStr)] string payloadJson,
            byte[] signature,
            int signatureLen);

        //--------------------------------------------------------------------
        // DID身份操作
        //--------------------------------------------------------------------
        [DllImport("keyauthcore.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern int KeyAuthCreateSignedDID(
            [MarshalAs(UnmanagedType.LPStr)] string algo,
            [MarshalAs(UnmanagedType.LPStr)] string priKey,
            [MarshalAs(UnmanagedType.LPStr)] string didInfo,
            out IntPtr didDocument);
            
        [DllImport("keyauthcore.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern int KeyAuthVerifyDID(
            [MarshalAs(UnmanagedType.LPStr)] string didDocument,
            out IntPtr pubKey);
            
        //--------------------------------------------------------------------
        // 区块链地址操作
        //--------------------------------------------------------------------
        [DllImport("keyauthcore.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern int KeyAuthGetAddresses(
            [MarshalAs(UnmanagedType.LPStr)] string pubKey,
            [MarshalAs(UnmanagedType.LPStr)] string algo,
            out IntPtr addresses);
            
        //--------------------------------------------------------------------
        // 区块链合约操作
        //--------------------------------------------------------------------
        [DllImport("keyauthcore.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern int KeyAuthQuery(
            [MarshalAs(UnmanagedType.LPStr)] string chainID,
            [MarshalAs(UnmanagedType.LPStr)] string nodeAddr,
            int nodePort,
            [MarshalAs(UnmanagedType.LPStr)] string contractName,
            [MarshalAs(UnmanagedType.LPStr)] string method,
            [MarshalAs(UnmanagedType.LPStr)] string privateKey,
            [MarshalAs(UnmanagedType.LPStr)] string paramsJSON,
            out IntPtr result);
            
        [DllImport("keyauthcore.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern int KeyAuthInvoke(
            [MarshalAs(UnmanagedType.LPStr)] string chainID,
            [MarshalAs(UnmanagedType.LPStr)] string nodeAddr,
            int nodePort,
            [MarshalAs(UnmanagedType.LPStr)] string contractName,
            [MarshalAs(UnmanagedType.LPStr)] string method,
            [MarshalAs(UnmanagedType.LPStr)] string privateKey,
            [MarshalAs(UnmanagedType.LPStr)] string paramsJSON,
            out IntPtr result);
            
        [DllImport("keyauthcore.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern void KeyAuthFree(IntPtr ptr);

        public KeyAuthCore(ILogger<KeyAuthCore> logger)
        {
            _logger = logger;
        }

        /// <summary>
        /// 生成密钥对
        /// </summary>
        /// <param name="algo">算法类型</param>
        /// <returns>公钥和私钥</returns>
        public (string publicKey, string privateKey, bool success) GenerateKeyPair(string algo)
        {
            try
            {
                IntPtr pubKeyPtr, priKeyPtr;
                int result = KeyAuthGenerateKeyPair(algo, out pubKeyPtr, out priKeyPtr);
                
                if (result == SUCCESS)
                {
                    string pubKey = Marshal.PtrToStringAnsi(pubKeyPtr) ?? string.Empty;
                    string priKey = Marshal.PtrToStringAnsi(priKeyPtr) ?? string.Empty;
                    
                    // 释放内存
                    KeyAuthFree(pubKeyPtr);
                    KeyAuthFree(priKeyPtr);
                    
                    return (pubKey, priKey, true);
                }
                else
                {
                    _logger.LogError($"生成密钥对失败，错误码: {result}");
                    return (string.Empty, string.Empty, false);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "生成密钥对时发生异常");
                return (string.Empty, string.Empty, false);
            }
        }
        
        
        /// <summary>
        /// 对请求数据进行签名（JWT格式的header和payload）
        /// 支持SM2+SM3或ECDSA+SHA256对JWT格式数据进行签名
        /// 可用于生成会话令牌，替代专用的JWT接口，实现自动化认证流程
        /// </summary>
        /// <param name="privateKey">私钥</param>
        /// <param name="headerJson">头部JSON</param>
        /// <param name="payloadJson">载荷JSON</param>
        /// <returns>签名结果</returns>
        public (byte[] signature, bool success) SignData(string privateKey, string headerJson, string payloadJson)
        {
            try
            {
                IntPtr signaturePtr;
                int signatureLen;
                
                int result = KeyAuthSignData(privateKey, headerJson, payloadJson, out signaturePtr, out signatureLen);
                
                if (result == SUCCESS)
                {
                    // 复制签名数据
                    byte[] signature = new byte[signatureLen];
                    Marshal.Copy(signaturePtr, signature, 0, signatureLen);
                    
                    // 释放内存
                    KeyAuthFree(signaturePtr);
                    
                    return (signature, true);
                }
                else
                {
                    _logger.LogError($"数据签名失败，错误码: {result}");
                    return (Array.Empty<byte>(), false);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "数据签名时发生异常");
                return (Array.Empty<byte>(), false);
            }
        }
        
        /// <summary>
        /// 验证请求数据的签名（JWT格式的header和payload）
        /// </summary>
        /// <param name="publicKey">公钥</param>
        /// <param name="headerJson">头部JSON</param>
        /// <param name="payloadJson">载荷JSON</param>
        /// <param name="signature">签名数据</param>
        /// <returns>验证结果</returns>
        public bool VerifyData(string publicKey, string headerJson, string payloadJson, byte[] signature)
        {
            try
            {
                int result = KeyAuthVerifyData(publicKey, headerJson, payloadJson, signature, signature.Length);
                return result == SUCCESS;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "验证数据签名时发生异常");
                return false;
            }
        }
        

        /// <summary>
        /// 创建并签名DID文档
        /// </summary>
        /// <param name="algo">算法类型</param>
        /// <param name="privateKey">私钥</param>
        /// <param name="didInfo">DID身份信息JSON</param>
        /// <returns>已签名的DID文档</returns>
        public (string didDocument, bool success) CreateSignedDID(string algo, string privateKey, string didInfo)
        {
            try
            {
                IntPtr didDocumentPtr;
                
                int result = KeyAuthCreateSignedDID(algo, privateKey, didInfo, out didDocumentPtr);
                
                if (result == SUCCESS)
                {
                    string didDocument = Marshal.PtrToStringAnsi(didDocumentPtr) ?? string.Empty;
                    
                    // 释放内存
                    KeyAuthFree(didDocumentPtr);
                    
                    return (didDocument, true);
                }
                else
                {
                    _logger.LogError($"创建DID文档失败，错误码: {result}");
                    return (string.Empty, false);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "创建DID文档时发生异常");
                return (string.Empty, false);
            }
        }
        
        /// <summary>
        /// 验证DID文档并提取公钥
        /// </summary>
        /// <param name="didDocument">DID文档</param>
        /// <returns>公钥</returns>
        public (string publicKey, bool success) VerifyDID(string didDocument)
        {
            try
            {
                IntPtr pubKeyPtr;
                
                int result = KeyAuthVerifyDID(didDocument, out pubKeyPtr);
                
                if (result == SUCCESS)
                {
                    string pubKey = Marshal.PtrToStringAnsi(pubKeyPtr) ?? string.Empty;
                    
                    // 释放内存
                    KeyAuthFree(pubKeyPtr);
                    
                    return (pubKey, true);
                }
                else
                {
                    _logger.LogError($"验证DID文档失败，错误码: {result}");
                    return (string.Empty, false);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "验证DID文档时发生异常");
                return (string.Empty, false);
            }
        }
        


        /// <summary>
        /// 获取公钥对应的多链地址
        /// </summary>
        /// <param name="publicKey">公钥PEM格式</param>
        /// <param name="algo">算法类型</param>
        /// <returns>地址信息JSON字符串</returns>
        public (string addresses, bool success) GetAddresses(string publicKey, string algo)
        {
            try
            {
                IntPtr addressesPtr;
                
                int result = KeyAuthGetAddresses(publicKey, algo, out addressesPtr);
                
                if (result == SUCCESS)
                {
                    string addresses = Marshal.PtrToStringAnsi(addressesPtr) ?? string.Empty;
                    
                    // 释放内存
                    KeyAuthFree(addressesPtr);
                    
                    return (addresses, true);
                }
                else
                {
                    _logger.LogError($"获取地址失败，错误码: {result}");
                    return (string.Empty, false);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取地址时发生异常");
                return (string.Empty, false);
            }
        }

        /// <summary>
        /// 区块链合约查询
        /// </summary>
        /// <param name="chainID">链ID</param>
        /// <param name="nodeAddr">节点地址</param>
        /// <param name="nodePort">节点端口</param>
        /// <param name="contractName">合约名称</param>
        /// <param name="method">方法名称</param>
        /// <param name="privateKey">私钥</param>
        /// <param name="paramsJSON">参数JSON</param>
        /// <returns>查询结果</returns>
        public (string result, bool success) Query(string chainID, string nodeAddr, int nodePort, string contractName, string method, string privateKey, string paramsJSON)
        {
            try
            {
                IntPtr resultPtr;
                int resultLen;

                int resultCode = KeyAuthQuery(chainID, nodeAddr, nodePort, contractName, method, privateKey, paramsJSON, out resultPtr);

                if (resultCode == SUCCESS)
                {
                    string result = Marshal.PtrToStringAnsi(resultPtr) ?? string.Empty;
                    KeyAuthFree(resultPtr);
                    return (result, true);
                }
                else
                {
                    _logger.LogError($"合约查询失败，错误码: {resultCode}");
                    return (string.Empty, false);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "合约查询时发生异常");
                return (string.Empty, false);
            }
        }

        /// <summary>
        /// 区块链合约调用
        /// </summary>
        /// <param name="chainID">链ID</param>
        /// <param name="nodeAddr">节点地址</param>
        /// <param name="nodePort">节点端口</param>
        /// <param name="contractName">合约名称</param>
        /// <param name="method">方法名称</param>
        /// <param name="privateKey">私钥</param>
        /// <param name="paramsJSON">参数JSON</param>
        /// <returns>调用结果</returns>
        public (string result, bool success) Invoke(string chainID, string nodeAddr, int nodePort, string contractName, string method, string privateKey, string paramsJSON)
        {
            try
            {
                IntPtr resultPtr;
                int resultLen;

                int resultCode = KeyAuthInvoke(chainID, nodeAddr, nodePort, contractName, method, privateKey, paramsJSON, out resultPtr);

                if (resultCode == SUCCESS)
                {
                    string result = Marshal.PtrToStringAnsi(resultPtr) ?? string.Empty;
                    KeyAuthFree(resultPtr);
                    return (result, true);
                }
                else
                {
                    _logger.LogError($"合约调用失败，错误码: {resultCode}");
                    return (string.Empty, false);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "合约调用时发生异常");
                return (string.Empty, false);
            }
        }
    }
} 